/*--------------------------------------------------------------------------
    This source file is part of Abraxas Game Engine
    For the latest info, see http://code.google.com/abraxasge/
    Copyright (C) 2009, Andrew LeRoy <aleroy@member.igda.org>
    ---

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA  02110-1301, USA.
--------------------------------------------------------------------------*/
#ifndef _Abx_Engine_hpp_
#define _Abx_Engine_hpp_

#include "AbxPrerequisites.hpp"
#include "AbxLongevity.hpp"
//#include "AbxSystem.hpp"
//#include "AbxSystemTypes.hpp"
#include "AbxString.hpp"
#include "loki/Singleton.h"


namespace Abx
{
    class _AbxExport EngineImpl
    {
    private:  // TYPES
        typedef ::std::vector<DynamicLibrary*> PluginLibs;
        typedef ::std::vector<Plugin*> Plugins;
        typedef ::std::vector<String> StringVector;
        
    public:   // C'STOR / D'STOR
        EngineImpl();
        ~EngineImpl();

    public:   // FUNCTIONS

#if ABX_PLATFORM == ABX_PLATFORM_WIN32
        std::vector<String> getArgs(int argc, String const& lpCmdLine);
#endif
        std::vector<String> getArgs(int argc, char* argv[]);

        bool startup(StringVector args);
        bool shutdown();
        bool update();
        
        bool run();
        
        void loadPlugins();
        void startupPlugins();
        void shutdownPlugins();
        void unloadPlugins();

        void loadPlugin(String const& pluginName);
        void registerPlugin(Plugin* plugin);
        void unregisterPlugin(Plugin* plugin);
        void unloadPlugin(String const& pluginName);
        Plugins const& getInstalledPlugins() const;
        
        bool isCreated() const
        {
            return (created_);
        }

//        template <typename S, class F>
//        void registerSystem(F* factory)
//        {
//            S::Instance().Register(factory);
//        }
//
//        template <typename S, class F>
//        void unregisterSystem(F* factory)
//        {
//            S::Instance().Unregister(factory);
//        }
//
//        template <typename S, class T>
//        T* createSystem(String const& typeName, String const& instanceName=StringTools::BLANK)
//        {
//            T* instance = S::Instance().Create(typeName, instanceName);
//            return instance;
//        }
//
//        template <typename S, class T>
//        void destroySystem(T* instance)
//        {
//            S::Instance().Destroy(instance);
//        }
//
//        template <typename S, class T>
//        T* getSystem(String const& name, bool byTypeName=false) const
//        {
//            T* instance = S::Instance().getSystem(name, byTypeName);
//            return instance;
//        }


    private:  // DATA
        const bool      created_;

    public:  // DATA
        PluginLibs      pluginLibs_;
        Plugins         plugins_;
        
        DefaultGraphicsSystemFactory* defaultGfx_;
    };
    
//    inline bool EngineImpl::isCreated() const
//
//
//    template <typename S>
//    inline void EngineImpl::registerSystem<S>(S::factory_type* factory)
//    {
//
//
//    }
//
//    template <typename S>
//    inline void EngineImpl::unregisterSystem<S>(S::factory_type* factory)
//
//    template <typename S>
//    inline S::type* EngineImpl::createSystem(String const& typeName, String const& instanceName)
//
//    template <typename S>
//    inline void EngineImpl::destroySystem(S::type* instance)
//
//    template <typename S>
//    inline S::type* EngineImpl::getSystem(String const& name, bool byTypeName=false) const



    inline uint32 GetLongevity(EngineImpl*) { return SLT_ENGINE; };
    
    typedef Loki::SingletonHolder< EngineImpl,
                                   Loki::CreateUsingNew,
                                   Loki::SingletonWithLongevity
                                 > Engine;
}
#endif // _Abx_Engine_hpp_
